/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under 
 * the Apache License, Version 2.0  (the "License"); you may not use this file
 * except in compliance with the License.  
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */


#ifndef S6A_DEFS_H_
#define S6A_DEFS_H_

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include <freeDiameter/freeDiameter-host.h>
#include <freeDiameter/libfdcore.h>

#include "mme_config.h"
#include "queue.h"


#define VENDOR_3GPP (10415)
#define APP_S6A     (16777251)

/* Errors that fall within the Permanent Failures category shall be used to
 * inform the peer that the request has failed, and should not be attempted
 * again. The Result-Code AVP values defined in Diameter Base Protocol RFC 3588
 * shall be applied. When one of the result codes defined here is included in a
 * response, it shall be inside an Experimental-Result AVP and the Result-Code
 * AVP shall be absent.
 */
#define DIAMETER_ERROR_USER_UNKNOWN             (5001)
#define DIAMETER_ERROR_ROAMING_NOT_ALLOWED      (5004)
#define DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION (5420)
#define DIAMETER_ERROR_RAT_NOT_ALLOWED          (5421)
#define DIAMETER_ERROR_EQUIPMENT_UNKNOWN        (5422)
#define DIAMETER_ERROR_UNKOWN_SERVING_NODE      (5423)

/* Result codes that fall within the transient failures category shall be used
 * to inform a peer that the request could not be satisfied at the time it was
 * received, but may be able to satisfy the request in the future. The
 * Result-Code AVP values defined in Diameter Base Protocol RFC 3588 shall be
 * applied. When one of the result codes defined here is included in a response,
 * it shall be inside an Experimental-Result AVP and the Result-Code AVP shall
 * be absent.
 */
#define DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE (4181)

#define DIAMETER_ERROR_IS_VENDOR(x)                    \
   ((x == DIAMETER_ERROR_USER_UNKNOWN)              || \
    (x == DIAMETER_ERROR_ROAMING_NOT_ALLOWED)       || \
    (x == DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION)  || \
    (x == DIAMETER_ERROR_RAT_NOT_ALLOWED)           || \
    (x == DIAMETER_ERROR_EQUIPMENT_UNKNOWN)         || \
    (x == DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE) || \
    (x == DIAMETER_ERROR_UNKOWN_SERVING_NODE))

typedef struct {
  struct dict_object *dataobj_s6a_vendor;     /* s6a vendor object */
  struct dict_object *dataobj_s6a_app;        /* s6a application object */

  /* Commands */
  struct dict_object *dataobj_s6a_air; /* s6a authentication request */
  struct dict_object *dataobj_s6a_aia; /* s6a authentication answer */
  struct dict_object *dataobj_s6a_ulr; /* s6a update location request */
  struct dict_object *dataobj_s6a_ula; /* s6a update location asnwer */
  struct dict_object *dataobj_s6a_pur; /* s6a purge ue request */
  struct dict_object *dataobj_s6a_pua; /* s6a purge ue answer */
  struct dict_object *dataobj_s6a_clr; /* s6a Cancel Location req */
  struct dict_object *dataobj_s6a_cla; /* s6a Cancel Location ans */
  struct dict_object *dataobj_s6a_rr;  /* s6a Reset req */
  struct dict_object *dataobj_s6a_ra;  /* s6a Reset ans */
  /** Notify Request to inform the UE about the handover (after timeout). */
  struct dict_object *dataobj_s6a_nr; /* s6a notify request */
  struct dict_object *dataobj_s6a_na; /* s6a notify answer */


  /* Some standard basic AVPs */
  struct dict_object *dataobj_s6a_origin_host;

  struct dict_object *dataobj_s6a_destination_host;
  struct dict_object *dataobj_s6a_destination_realm;
  struct dict_object *dataobj_s6a_user_name;
  struct dict_object *dataobj_s6a_session_id;
  struct dict_object *dataobj_s6a_auth_session_state;
  struct dict_object *dataobj_s6a_result_code;
  struct dict_object *dataobj_s6a_experimental_result;

  /* S6A specific AVPs */
  struct dict_object *dataobj_s6a_visited_plmn_id;
  struct dict_object *dataobj_s6a_rat_type;
  struct dict_object *dataobj_s6a_cancellation_type;
  struct dict_object *dataobj_s6a_ulr_flags;
  struct dict_object *dataobj_s6a_ula_flags;
  struct dict_object *dataobj_s6a_clr_flags;
  struct dict_object *dataobj_s6a_nr_flags;
  struct dict_object *dataobj_s6a_subscription_data;
  struct dict_object *dataobj_s6a_req_eutran_auth_info;
  struct dict_object *dataobj_s6a_number_of_requested_vectors;
  struct dict_object *dataobj_s6a_immediate_response_pref;
  struct dict_object *dataobj_s6a_authentication_info;
  struct dict_object *dataobj_s6a_re_synchronization_info;
  struct dict_object *dataobj_s6a_service_selection;
  struct dict_object *dataobj_s6a_ue_srvcc_cap;

  /* Handlers */
  struct disp_hdl *aia_hdl;   /* Authentication Information Answer Handle */
  struct disp_hdl *ula_hdl;   /* Update Location Answer Handle */
  struct disp_hdl *pua_hdl;   /* Purge UE Answer Handle */
  struct disp_hdl *clr_hdl;   /* Cancel Location Request Handle */
  struct disp_hdl *rr_hdl;    /* Reset Request Handle */
  struct disp_hdl *na_hdl;    /* Reset Request Handle */
} s6a_fd_cnf_t;

extern s6a_fd_cnf_t s6a_fd_cnf;

#define ULR_SINGLE_REGISTRATION_IND      (1U)
#define ULR_S6A_S6D_INDICATOR            (1U << 1)
#define ULR_SKIP_SUBSCRIBER_DATA         (1U << 2)
#define ULR_GPRS_SUBSCRIPTION_DATA_IND   (1U << 3)
#define ULR_NODE_TYPE_IND                (1U << 4)
#define ULR_INITIAL_ATTACH_IND           (1U << 5)
#define ULR_PS_LCS_SUPPORTED_BY_UE       (1U << 6)

/** Flags for notify request. */
#define NR_SINGLE_REGISTRATION_IND       (1U)

#define ULA_SEPARATION_IND          (1U)

#define FLAG_IS_SET(x, flag)   \
    ((x) & (flag))

#define FLAGS_SET(x, flags) \
    ((x) |= (flags))

#define FLAGS_CLEAR(x, flags)   \
    ((x) = (x) & ~(flags))

/* IANA defined IP address type */
#define IANA_IPV4   (0x1)
#define IANA_IPV6   (0x2)

#define AVP_CODE_3GPP_CHARGING_CHARACTERISTICS     (13)
#define AVP_CODE_VENDOR_ID                         (266)
#define AVP_CODE_EXPERIMENTAL_RESULT               (297)
#define AVP_CODE_EXPERIMENTAL_RESULT_CODE          (298)
#define AVP_CODE_MIP_HOME_AGENT_ADDRESS            (334)
#define AVP_CODE_MIP6_AGENT_INFO                   (486)
#define AVP_CODE_SERVICE_SELECTION                 (493)
#define AVP_CODE_BANDWIDTH_UL                      (516)
#define AVP_CODE_BANDWIDTH_DL                      (515)
#define AVP_CODE_MSISDN                            (701)
#define AVP_CODE_SERVED_PARTY_IP_ADDRESS           (848)
#define AVP_CODE_QCI                               (1028)
#define AVP_CODE_ALLOCATION_RETENTION_PRIORITY     (1034)
#define AVP_CODE_PRIORITY_LEVEL                    (1046)
#define AVP_CODE_PRE_EMPTION_CAPABILITY            (1047)
#define AVP_CODE_PRE_EMPTION_VULNERABILITY         (1048)
#define AVP_CODE_SUBSCRIPTION_DATA                 (1400)
#define AVP_CODE_TERMINAL_INFO                     (1401)
#define AVP_CODE_IMEI                              (1402)
#define AVP_CODE_SOFTWARE_VERSION                  (1403)
#define AVP_CODE_QOS_SUBSCRIBED                    (1404)
#define AVP_CODE_ULR_FLAGS                         (1405)
#define AVP_CODE_ULA_FLAGS                         (1406)
#define AVP_CODE_VISITED_PLMN_ID                   (1407)
#define AVP_CODE_REQUESTED_EUTRAN_AUTHENTICATION_INFO (1408)
#define AVP_CODE_NUMBER_OF_REQUESTED_VECTORS       (1410)
#define AVP_CODE_RE_SYNCHRONIZATION_INFO           (1411)
#define AVP_CODE_IMMEDIATE_RESPONSE_PREFERRED      (1412)
#define AVP_CODE_AUTHENTICATION_INFO               (1413)
#define AVP_CODE_E_UTRAN_VECTOR                    (1414)
#define AVP_CODE_UTRAN_VECTOR                      (1415)
#define AVP_CODE_GERAN_VECTOR                      (1416)
#define AVP_CODE_NETWORK_ACCESS_MODE               (1417)
#define AVP_CODE_HPLMN_ODB                         (1418)
#define AVP_CODE_ITEM_NUMBER                       (1419)
#define AVP_CODE_CANCELLATION_TYPE                 (1420)
#define AVP_CODE_DSR_FLAGS                         (1421)
#define AVP_CODE_DSA_FLAGS                         (1422)
#define AVP_CODE_CONTEXT_IDENTIFIER                (1423)
#define AVP_CODE_SUBSCRIBER_STATUS                 (1424)
#define AVP_CODE_OPERATOR_DETERMINED_BARRING       (1425)
#define AVP_CODE_ACCESS_RESTRICTION_DATA           (1426)
#define AVP_CODE_APN_OI_REPLACEMENT                (1427)
#define AVP_CODE_ALL_APN_CONFIG_INC_IND            (1428)
#define AVP_CODE_APN_CONFIGURATION_PROFILE         (1429)
#define AVP_CODE_APN_CONFIGURATION                 (1430)
#define AVP_CODE_EPS_SUBSCRIBED_QOS_PROFILE        (1431)
#define AVP_CODE_VPLMN_DYNAMIC_ADDRESS_ALLOWED     (1432)
#define AVP_CODE_STN_SR                            (1433)
#define AVP_CODE_ALERT_REASON                      (1434)
#define AVP_CODE_AMBR                              (1435)
#define AVP_CODE_CSG_SUBSCRIPTION_DATA             (1436)
#define AVP_CODE_CSG_ID                            (1437)
#define AVP_CODE_PDN_GW_ALLOCATION_TYPE            (1438)
#define AVP_CODE_EXPIRATION_DATE                   (1439)
#define AVP_CODE_RAT_FREQUENCY_SELECTION_PRIORITY_ID (1440)
#define AVP_CODE_IDA_FLAGS                         (1441)
#define AVP_CODE_PUA_FLAGS                         (1442)
#define AVP_CODE_NOR_FLAGS                         (1443)
#define AVP_CODE_USER_ID                           (1444)
#define AVP_CODE_EQUIPMENT_STATUS                  (1445)
#define AVP_CODE_REGIONAL_SUBSCRIPTION_ZONE_CODE   (1446)
#define AVP_CODE_RAND                              (1447)
#define AVP_CODE_XRES                              (1448)
#define AVP_CODE_AUTN                              (1449)
#define AVP_CODE_KASME                             (1450)
#define AVP_CODE_TRACE_COLLECTION_ENTITY           (1452)
#define AVP_CODE_KC                                (1453)
#define AVP_CODE_SRES                              (1454)
#define AVP_CODE_PDN_TYPE                          (1456)
#define AVP_CODE_ROAMING_RESTRICTED_DUE_TO_UNSUPPORTED_FEATURE (1457)
#define AVP_CODE_SUBSCRIBED_PERIODIC_RAU_TAU_TIMER (1619)
#define AVP_CODE_PUR_FLAGS                         (1635)
#define AVP_CODE_Equivalent_PLMN_List              (1637)
#define AVP_CODE_CLR_FLAGS                         (1638)
#define AVP_CODE_UVR_FLAGS                         (1639)
#define AVP_CODE_UVA_FLAGS                         (1640)
#define AVP_CODE_TIME_ZONE                         (1642)
#define AVP_CODE_LOCAL_TIME_ZONE                   (1649)
#define AVP_CODE_DAYLIGHT_SAVING_TIME              (1650)
#define AVP_CODE_Reset_ID                          (1670)
#define AVP_CODE_ADJACENT_PLMNS                    (1672)
#define AVP_CODE_ADDITIONAL_CONTEXT_ID             (1683)
#define AVP_CODE_SUBSCRIPTION_SCEF_REALM           (1684)
#define AVP_CODE_SUBSCRIPTION_DATA_DELETION        (1685)
#define AVP_CODE_PREFERRED_DATA_MODE               (1686)
#define AVP_CODE_Emergency_Info                    (1687)
#define AVP_CODE_V2X_SUBSCRIPTION_DATA             (1688)
#define AVP_CODE_V2X_PERMISSION                    (1689)

int s6a_init(const mme_config_t *mme_config);

int s6a_fd_new_peer(void);

void s6a_peer_connected_cb(struct peer_info *info, void *arg);

int s6a_fd_init_dict_objs(void);

int s6a_parse_subscription_data(struct avp *avp_subscription_data,
                                subscription_data_t *subscription_data);

int s6a_parse_experimental_result(struct avp *avp, s6a_experimental_result_t *ptr);
char *experimental_retcode_2_string(uint32_t ret_code);
char *retcode_2_string(uint32_t ret_code);


#endif /* S6A_DEFS_H_ */
